package com.lw.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.idev.excel.EasyExcel;
import cn.idev.excel.ExcelWriter;
import com.lw.common.aop.LogOperation;
import com.lw.common.enums.LogModuleEnum;
import com.lw.common.utils.ExcelUtils;
import com.lw.common.utils.ResultVo;
import com.lw.common.vo.Option;
import com.lw.common.vo.PasswordVo;
import com.lw.common.vo.UserVo;
import com.mybatisflex.core.paginate.Page;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import com.lw.entity.TbUser;
import com.lw.service.TbUserService;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * 用户信息表 控制层。
 *
 * @author lw
 * @since 2025年05月15日 08:17:48
 */
@RestController
@Tag(name = "01-用户信息表接口")
@RequestMapping("/tbUser")
public class TbUserController {

    @Resource
    private TbUserService tbUserService;

    /**
     * 添加用户信息表。
     *
     * @param tbUser 用户信息表
     * @return {@code true} 添加成功，{@code false} 添加失败
     */
    @PostMapping("saveUser")
    @Operation(description = "保存用户信息表")
    @SaCheckPermission("sys:user:add")
    @LogOperation(module = LogModuleEnum.LOG_USER, value = "保存用户信息表", params = false)
    public ResultVo<Boolean> save(@RequestBody @Parameter(description = "用户信息表") TbUser tbUser) {
        return ResultVo.success(tbUserService.saveUser(tbUser));
    }

    /**
     * 根据主键删除用户信息表。
     *
     * @param ids 集合
     * @return {@code true} 删除成功，{@code false} 删除失败
     */
    @DeleteMapping("deleteUser/{ids}")
    @Operation(description = "根据主键删除用户信息表")
    @LogOperation(module = LogModuleEnum.LOG_USER, value = "根据主键删除用户信息表", result = true)
    @SaCheckPermission("sys:user:delete")
    public ResultVo<Boolean> deleteUser(@PathVariable("ids") @Parameter(description = "用户信息表主键") String ids) {
        return ResultVo.success(tbUserService.deleteUser(ids));
    }

    /**
     * 根据主键更新用户信息表。
     *
     * @param tbUser 用户信息表
     * @return {@code true} 更新成功，{@code false} 更新失败
     */
    @PutMapping("updateUser")
    @Operation(description = "根据主键更新用户信息表")
    @SaCheckPermission("sys:user:edit")
    @LogOperation(module = LogModuleEnum.LOG_USER, value = "根据主键更新用户信息表", params = false)
    public ResultVo<Boolean> update(@RequestBody @Parameter(description = "用户信息表主键") TbUser tbUser) {
        return ResultVo.success(tbUserService.updateUser(tbUser));
    }

    @PutMapping("updateUserProfile")
    @Operation(description = "更新用户个人信息")
    @LogOperation(module = LogModuleEnum.LOG_USER, value = "更新用户个人信息", params = false)
    public ResultVo<Boolean> updateUserProfile(@RequestBody @Parameter(description = "用户信息表主键") TbUser tbUser) {
        return ResultVo.success(tbUserService.updateUserProfile(tbUser));
    }

    @PutMapping("resetPwd/{id}")
    @Operation(description = "重置密码")
    @SaCheckPermission("ys:user:reset-password")
    @LogOperation(module = LogModuleEnum.LOG_USER, value = "重置密码", params = false)
    public ResultVo<Boolean> resetPwd(@PathVariable("id") Long id, String password) {
        return ResultVo.success(tbUserService.resetPwd(id, password));
    }

    @PutMapping("updatePassword")
    @Operation(description = "修改密码")
    @LogOperation(module = LogModuleEnum.LOG_USER, value = "修改密码", params = false)
    public ResultVo<Boolean> updatePassword(@RequestBody PasswordVo passwordVo) {
        return ResultVo.success(tbUserService.updatePassword(passwordVo));
    }


    /**
     * 查询所有用户信息表。
     *
     * @return 所有数据
     */
    @GetMapping("list")
    @Operation(description = "查询所有用户信息表")
    public ResultVo<List<TbUser>> list() {
        return ResultVo.success(tbUserService.list());
    }

    /**
     * 根据用户信息表主键获取详细信息。
     *
     * @param id 用户信息表主键
     * @return 用户信息表详情
     */
    @GetMapping("getUserInfo/{id}")
    @Operation(description = "根据主键获取用户信息表")
    public ResultVo<TbUser> getUserInfo(@PathVariable("id") Long id) {
        return ResultVo.success(tbUserService.getUserInfo(id));
    }

    /**
     * 分页查询用户信息表。
     *
     * @return 分页对象
     */
    @GetMapping("getUserPage")
    @Operation(description = "分页查询用户信息表")
    public ResultVo<Page<TbUser>> getUserPage(UserVo userVo) {
        return ResultVo.success(tbUserService.getUserPage(userVo));
    }

    //用户导出excel
    @GetMapping("exportExcel")
    @Operation(description = "导出用户信息表")
    public void exportExcel(UserVo userVo, HttpServletResponse response) throws IOException {
        String fileName = "用户列表.xlsx";
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));
        List<TbUser> exportUserList = tbUserService.getUserList(userVo);
        EasyExcel.write(response.getOutputStream(), TbUser.class).sheet("用户列表")
                .doWrite(exportUserList);
    }

    //用户导入excel魔板下载
    @Operation(summary = "用户导入模板下载")
    @GetMapping("/downloadUserTemplate")
    @LogOperation(module = LogModuleEnum.LOG_USER, value = "用户导入模板下载", params = false)
    public void downloadUserTemplate(HttpServletResponse response) {
        String fileName = "用户导入模板.xlsx";
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));
        String fileClassPath = "templates" + File.separator + fileName;
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(fileClassPath);

        try (ServletOutputStream outputStream = response.getOutputStream();
             ExcelWriter excelWriter = EasyExcel.write(outputStream).withTemplate(inputStream).build()) {
            excelWriter.finish();
        } catch (IOException e) {
            throw new RuntimeException("用户导入模板下载失败", e);
        }
    }

    @Operation(summary = "导入用户")
    @PostMapping("/importUser")
    @LogOperation(module = LogModuleEnum.LOG_USER, value = "导入用户", params = false)
    public ResultVo<String> importUser(MultipartFile file) throws IOException {
        ExcelUtils.importExcel(file.getInputStream(), TbUser.class, new UserImportListener());
        return ResultVo.success("导入成功");
    }

    //获取用户下拉列表
    @GetMapping("getUserOptionList")
    @Operation(description = "获取用户下路列表")
    public ResultVo<List<Option<Long>>> getUserOptionList() {
        return ResultVo.success(tbUserService.getUserOptionList());
    }

}
